1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20
21 import com.google.common.primitives.Ints;
22
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Set;
26
27
28
29
30
31
32 class CollectionBenchmarkSampleData {
33 private final boolean isUserTypeFast;
34 private final SpecialRandom random;
35 private final double hitRate;
36 private final int size;
37
38 private final Set<Element> valuesInSet;
39 private final Element[] queries;
40
41 CollectionBenchmarkSampleData(int size) {
42 this(true, new SpecialRandom(), 1.0, size);
43 }
44
45 CollectionBenchmarkSampleData(
46 boolean isUserTypeFast,
47 SpecialRandom random,
48 double hitRate,
49 int size) {
50 this.isUserTypeFast = isUserTypeFast;
51 this.random = checkNotNull(random);
52 this.hitRate = hitRate;
53 this.size = size;
54
55 this.valuesInSet = createData();
56 this.queries = createQueries(valuesInSet, 1024);
57 }
58
59 Set<Element> getValuesInSet() {
60 return valuesInSet;
61 }
62
63 Element[] getQueries() {
64 return queries;
65 }
66
67 private Element[] createQueries(Set<Element> elementsInSet, int numQueries) {
68 List<Element> queryList = Lists.newArrayListWithCapacity(numQueries);
69
70 int numGoodQueries = (int) (numQueries * hitRate + 0.5);
71
72
73 int size = elementsInSet.size();
74 if (size > 0) {
75 int minCopiesOfEachGoodQuery = numGoodQueries / size;
76 int extras = numGoodQueries % size;
77
78 for (int i = 0; i < minCopiesOfEachGoodQuery; i++) {
79 queryList.addAll(elementsInSet);
80 }
81 List<Element> tmp = Lists.newArrayList(elementsInSet);
82 Collections.shuffle(tmp, random);
83 queryList.addAll(tmp.subList(0, extras));
84 }
85
86
87 while (queryList.size() < numQueries) {
88 Element candidate = newElement();
89 if (!elementsInSet.contains(candidate)) {
90 queryList.add(candidate);
91 }
92 }
93 Collections.shuffle(queryList, random);
94 return queryList.toArray(new Element[0]);
95 }
96
97 private Set<Element> createData() {
98 Set<Element> set = Sets.newHashSetWithExpectedSize(size);
99 while (set.size() < size) {
100 set.add(newElement());
101 }
102 return set;
103 }
104
105 private Element newElement() {
106 int value = random.nextInt();
107 return isUserTypeFast
108 ? new Element(value)
109 : new SlowElement(value);
110 }
111
112 static class Element implements Comparable<Element> {
113 final int hash;
114 Element(int hash) {
115 this.hash = hash;
116 }
117 @Override public boolean equals(Object obj) {
118 return this == obj
119 || (obj instanceof Element && ((Element) obj).hash == hash);
120 }
121 @Override public int hashCode() {
122 return hash;
123 }
124 @Override
125 public int compareTo(Element that) {
126 return Ints.compare(hash, that.hash);
127 }
128 @Override public String toString() {
129 return String.valueOf(hash);
130 }
131 }
132
133 static class SlowElement extends Element {
134 SlowElement(int hash) {
135 super(hash);
136 }
137 @Override public boolean equals(Object obj) {
138 return slowItDown() != 1 && super.equals(obj);
139 }
140 @Override public int hashCode() {
141 return slowItDown() + hash;
142 }
143 @Override public int compareTo(Element e) {
144 int x = slowItDown();
145 return x + super.compareTo(e) - x;
146 }
147 static int slowItDown() {
148 int result = 0;
149 for (int i = 1; i <= 1000; i++) {
150 result += i;
151 }
152 return result;
153 }
154 }
155 }